package com.zxy.express.filter;

import com.autopai.base.common.tools.utils.JsonUtil;
import com.autopai.base.common.web.model.RestResult;
import com.zxy.express.common.MyConstant;
import com.zxy.express.exception.ModuleErrorCode;
import com.zxy.express.util.JwtUtils;
import io.jsonwebtoken.Claims;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

/**
 * 校验token
 *
 * @author zhangxiying
 * @version 1.0
 * @date 2025/07/01
 */
@Slf4j
@Data
@Configuration
@ConfigurationProperties(prefix = "expresscore")
public class TokenValidateFilter extends OncePerRequestFilter {

    private final AntPathMatcher antPathMatcher = new AntPathMatcher();
    /**
     * 不拦截的urls
     */
    private List<String> ignoringUrls;

    @Autowired
    private JwtUtils jwtUtils;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                    FilterChain chain) throws ServletException, IOException {
        String requestUri = request.getRequestURI();
        // 请求放行，无需验证权限
        if (HttpMethod.OPTIONS.matches(request.getMethod()) || pathMatcher(requestUri)) {
            chain.doFilter(request, response);
            return;
        }
        // 获取用户token
        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token)) {
            token=request.getParameter("token");
            if(StringUtils.isEmpty(token)) {
                // 没权限访问，直接返回
                outPutResponse(response, new RestResult().error(ModuleErrorCode.TOKEN_IS_NULL));
                return;
            }
        }
        // 是否过期
        Claims claims = jwtUtils.getClaimByToken(token);
        if (claims == null || jwtUtils.isTokenExpired(claims.getExpiration())) {
            outPutResponse(response, new RestResult().error(ModuleErrorCode.TOKEN_EXPIRED));
            return;
        }
        // 获取用户ID
        String userId =claims.getSubject();
        // 是否退登
//        String token1=(String) redisUtils.get(CacheKey.getWorkUserTokenKey(userId));
//        if(StringUtils.isEmpty(token1)){
//            log.info("已退登{}",userId);
//            outPutResponse(response, new RestResult().error(ModuleErrorCode.TOKEN_EXPIRED));
//        }

        if (!StringUtils.isEmpty(userId)) {
            MutableHttpServletRequest mutableRequest = new MutableHttpServletRequest(request);
            mutableRequest.putHeader(MyConstant.USER_ID, userId);
            chain.doFilter(mutableRequest, response);
        } else {
            chain.doFilter(request, response);
        }
    }


    public void outPutResponse(ServletResponse res, RestResult result) {
        res.setContentType(MediaType.APPLICATION_JSON_UTF8.toString());
        PrintWriter out = null;
        try {
            out = res.getWriter();
            out.print(JsonUtil.obj2String(result));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            out.flush();
            out.close();
        }
    }

    private boolean pathMatcher(String requestUri) {
        for (String url : ignoringUrls) {
            if (antPathMatcher.match(url, requestUri)) {
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        AntPathMatcher antPathMatcher = new AntPathMatcher();
        System.out.println(antPathMatcher.match("/*.html", "/doc.html"));
    }
}